Skip to content

refactor: unify generate() and stream() methods to base Client class#13

Merged
Kamilbenkirane merged 1 commit intomainfrom
refactor/unify-generate-stream-to-base-client
Nov 6, 2025
Merged

refactor: unify generate() and stream() methods to base Client class#13
Kamilbenkirane merged 1 commit intomainfrom
refactor/unify-generate-stream-to-base-client

Conversation

@Kamilbenkirane
Copy link
Copy Markdown
Member

Summary

This PR unifies the generate() and stream() methods in the base Client class, reducing code duplication across providers and improving maintainability.

Changes Made

Core Architecture

  • Unified generate() method: Moved common orchestration logic to base Client class
  • Unified stream() method: Moved common streaming logic to base Client class
  • New abstract methods: Added _create_inputs(), _make_request(), _output_class(), _stream_class(), _make_stream_request()
  • Model streaming field: Added streaming: bool field to Model class to indicate per-model streaming support

Files Changed

  • src/celeste/client.py: Unified generate/stream methods, added abstract methods
  • src/celeste/models.py: Added streaming field to Model class
  • src/celeste/artifacts.py: Improved docstring for Artifact class
  • tests/unit_tests/test_client.py: Updated ConcreteClient to implement new abstract methods

Benefits

  • Reduced duplication: Common logic centralized in base class
  • Consistency: All providers follow the same pattern
  • Maintainability: Changes to core logic only need to be made in one place
  • Type safety: Better type narrowing with abstract methods

@claude
Copy link
Copy Markdown

claude Bot commented Nov 6, 2025

Pull Request Review: Unify generate() and stream() Methods

Summary

This PR refactors the base Client class to consolidate common logic for generate() and stream() methods, reducing code duplication across providers. The refactoring introduces several new abstract methods that providers must implement, creating a cleaner separation of concerns.

Code Quality & Architecture

Strengths

  1. Excellent Separation of Concerns: The refactoring nicely separates framework orchestration (in base class) from provider-specific logic (abstract methods). This is a solid application of the Template Method pattern.

  2. Type Safety: Good use of generics maintains type safety throughout the hierarchy.

  3. Reduced Duplication: Moving the common orchestration logic to the base class eliminates repetition across provider implementations.

  4. Consistent Error Handling: Centralizing _handle_error_response ensures uniform error handling across all providers.

  5. Clear Documentation: Method docstrings are well-written and explain the purpose clearly.

Areas for Improvement

1. Missing _transform_output Reference in generate()

Location: src/celeste/client.py:56-60

The stream() method references self._transform_output at line 84, but generate() doesn't apply output transformations. This creates an inconsistency between streaming and non-streaming paths.

Recommendation: Apply _transform_output in generate() as well to ensure consistent behavior.

2. Type Ignore Comment Needs Justification

Location: src/celeste/client.py:82

The type: ignore comment suggests a type mismatch that should either be fixed or documented.

3. Streaming Field Initialization in Model Registry

Location: src/celeste/models.py:55

When merging models with the same (id, provider) key, the streaming field is only set during initial registration and never updated. If the same model is registered multiple times with different streaming values, only the first value will be used.

Recommendation: Consider validating consistency or documenting the expected behavior.

Potential Bugs

Critical Issue: Error Handling in generate()

Location: src/celeste/client.py:53-55

Line 55 calls response.json() without error handling. If the response body isn't valid JSON, this will raise a JSONDecodeError that isn't caught.

Recommendation: Wrap the json() call in try-except to provide better error messages.

Performance Considerations

Good Performance Design

  1. Lazy Stream Evaluation: The stream() method returns a stream iterator immediately without making the request upfront, allowing for proper async iteration.

  2. Shared HTTP Client: Using http_client property with connection pooling is excellent for performance.

Security Concerns

Security Strengths

  1. API Key Handling: Proper use of SecretStr with exclude=True ensures API keys aren't accidentally logged or serialized.

  2. Error Message Safety: The error handling carefully extracts error messages without exposing sensitive data.

Minor Security Consideration

Location: src/celeste/client.py:153

Using response.text as a fallback could potentially expose sensitive information. Consider truncating to 200 characters.

Test Coverage

Test Updates Look Good

The test file updates properly implement all new abstract methods with reasonable mock implementations.

Missing Test Coverage

Consider adding tests for:

  1. Error scenarios in generate(): What happens when response.json() fails?
  2. Parameter transformation in generate(): Currently only stream() is tested with transformations
  3. Multiple streaming values: Test the behavior when a model is registered multiple times

Overall Assessment

This is a well-designed refactoring that significantly improves code organization and maintainability. The Template Method pattern is appropriately applied, and the separation between framework and provider logic is clean.

Priority Action Items:

  1. HIGH: Fix the missing output transformation in generate() method
  2. HIGH: Add error handling for response.json() call
  3. MEDIUM: Address the streaming field merge behavior in model registry
  4. MEDIUM: Remove or explain the type: ignore comment
  5. LOW: Add test coverage for the gaps mentioned above

Recommendation: Approve with Minor Changes

The core architecture is sound, but the output transformation inconsistency should be addressed before merging to ensure consistent behavior between generate() and stream().


Great work on this refactoring! The codebase will be much more maintainable going forward.

@Kamilbenkirane Kamilbenkirane merged commit 36219d3 into main Nov 6, 2025
11 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant